
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//#include "StdAfx.h"
#include "game.h"
#include "ASprite.h"
#include "CWriteFile.h"
#include "CReadFile.h"
#include "Font.h"
#include "ParticleSystem/ParticleHolderManager.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////////////////// 

void CGame::SignalRobotDead()
{
	if(m_GameplayPrepareEnd >0)
	{
		m_GameplayPrepareEnd--;
	}
}


void CGame::State_Gameplay(int depth, int mode)
{
	if(mode == (StateMachineMode::Update))
	{
		if(nCGame::_gamePaused)
			return;

		if(m_cinematic->GetState() == E_CINEMATIC_FINISHED)
		{
			if(m_GameplayPrepareEnd == -1)
			{
				m_GameplayPrepareEnd = 0;
				GameObjectListInterface& objs = GetGameObjectManager()->GetFarRangeObjects();
				int numObj = objs.GetCount();

				for(int i=0;i<numObj;i++)
				{
					if(objs[i]->GetObjectType() == Object_Robot &&
						objs[i]->IsEnabled())
					{
						m_GameplayPrepareEnd++;
					}
				}
			}
			else if(m_GameplayPrepareEnd == 0)
			{
				m_objectManager->UpdateGameObjects();
				m_itemManager->UpdateAll();
				return;
			}
		}
		CinematicManager::Instance()->update(GetGameplayTimeStep());

		if(GetItemManager()->GetCurrentBall() != NULL &&
			GetItemManager()->GetCurrentBall()->m_state == BALL_STATE_IDLE)
		{
			if(moTouchInput.IsMouseDown())
			{
				if(moTouchInput.GetMousePosY() <GROUND_HEIGHT)
				{
					m_GameplayNeedShowPath = true;
					//GetItemManager()->m_GameplayCrtBallon->SetNoDisplacement();
					//GetItemManager()->m_GameplayCrtBallon->m_state = BALL_STATE_IDLE;
					//GetItemManager()->m_GameplayCrtBallon->SetPosition(m_GameplayStartPointX,m_GameplayStartPointY);
					b2Vec2 pos = ConvertScreenToWorld(moTouchInput.GetMousePosX(),moTouchInput.GetMousePosY());
					m_GameplayEndPointX = pos.x;//moTouchInput.GetMousePosX();
					m_GameplayEndPointY = pos.y;//moTouchInput.GetMousePosY();
					m_GameplayControlPointX = m_GameplayEndPointX;
					m_GameplayControlPointY = m_GameplayEndPointY;
				}

			}
			else if(moTouchInput.IsMouseUp())
			{
				if(moTouchInput.GetMousePosY() <GROUND_HEIGHT)
				{
					m_GameplayNeedShowPath = false;
					//GetItemManager()->m_GameplayCrtBallon->SetPosition(m_GameplayStartPointX,m_GameplayStartPointY);
					GetItemManager()->ThrowBall(m_GameplayControlPointX,m_GameplayControlPointY,m_GameplayEndPointX,m_GameplayEndPointY);

					float t = 0.0f;
					float step = 0.01f;
					float tdir = 0;
					float sx,sy,ex,ey;
					sx = m_GameplayStartPointX;
					sy = m_GameplayStartPointY;
			
					float speed =20;
					while(t<=1)
					{
						t+=step;
						ex = (1-t)*(1-t)*m_GameplayStartPointX + 2*(1-t)*t*m_GameplayControlPointX + t*t*m_GameplayEndPointX;
						ey = (1-t)*(1-t)*m_GameplayStartPointY + 2*(1-t)*t*m_GameplayControlPointY + t*t*m_GameplayEndPointY;

						float dir = sqrt((float)((ex-sx)*(ex-sx) + (ey-sy)*(ey-sy)));
						if(abs(tdir + dir - speed)<2)
						{
							printf("(%f)\n",t);
							sx = ex;
							sy = ey;
							tdir = 0;
							step = 0.01;
						}
						else
						{
							if(tdir+dir < speed)
							{
								tdir += dir;
								sx = ex;
								sy = ey;
							}
							else
							{
								t-=step;
								step/=2;
							}
						}

						
					}
				}
			}
			else if(moTouchInput.IsMouseDragging())
			{
				//if(moTouchInput.GetMousePosY() <GROUND_HEIGHT)
				{
					b2Vec2 pos = ConvertScreenToWorld(moTouchInput.GetMousePosX(),moTouchInput.GetMousePosY());
					m_GameplayControlPointX = pos.x;//moTouchInput.GetMousePosX();
					m_GameplayControlPointY = pos.y;//moTouchInput.GetMousePosY();
					/*m_GameplayStartPointX = moTouchInput.GetMousePosX();
					m_GameplayStartPointY = moTouchInput.GetMousePosY();*/
					//GetItemManager()->m_GameplayCrtBallon->SetPosition(m_GameplayStartPointX,m_GameplayStartPointY);
				}
			}
		

			/*if(nCGame::_gameNeedSave)
			{
				save_t[4] = GetItemManager()->m_GameplayCrtBallon->m_Speed.X;
				save_t[5] = GetItemManager()->m_GameplayCrtBallon->m_Speed.Y;
				save_t[6] = GetItemManager()->m_GameplayCrtBallon->m_lastCollisionPoint.X;
				save_t[7] = GetItemManager()->m_GameplayCrtBallon->m_lastCollisionPoint.Y;
				nCGame::_gameNeedSave = false;
			}*/
			if(nCGame::_gameRestart)
			{
				m_cinematic->reset();
				//if(m_GameplayCrtBallon->m_state == 0)
				/*{
					m_GameplayEndPointX = save_t[0];
					m_GameplayEndPointY = save_t[1];
					m_GameplayControlPointX = save_t[2];
					m_GameplayControlPointY = save_t[3];
					GetItemManager()->m_GameplayCrtBallon->SetPosition(m_GameplayStartPointX,m_GameplayStartPointY);
					GetItemManager()->m_GameplayCrtBallon->SetPath(m_GameplayControlPointX,m_GameplayControlPointY,m_GameplayEndPointX,m_GameplayEndPointY);
				}*/
				/*else if(m_GameplayCrtBallon->m_state == 1)
				{
					 m_GameplayCrtBallon->m_Speed.X = save_t[4];
					 m_GameplayCrtBallon->m_Speed.Y = save_t[5];
					 m_GameplayCrtBallon->SetPosition(save_t[6],save_t[7]);	
					 m_GameplayCrtBallon->m_lastCollisionPoint.X = save_t[6];
					 m_GameplayCrtBallon->m_lastCollisionPoint.Y = save_t[7];
				}*/
				nCGame::_gameRestart = false;
			}
		}

		m_objectManager->UpdateGameObjects();
		m_itemManager->UpdateAll();
		ParticleHolderManager::Update();

	}
	else if(mode == (StateMachineMode::Draw2D))
	{		
		GFX_Clear(0xffffffff);
		GFX_Clear(0xff000000);

		//ASprite* bottle = GetResManager()->getSprite(SPRITE_BOTTLE);
		
		//bottle->PaintFrame(0,m_GameplayStartPointX,m_GameplayStartPointY);
		ASprite* bg = GetResManager()->getSprite(SPRITE_INGAME_GROUNDS_1);
		bg->PaintFrame(0,0,0);
		m_objectManager->DrawGameObjects();
		m_ScreenManager->DrawAll();
		m_itemManager->DrawAll();

		getGfx()->SetColor(0xffff0000);
		for(int i=0;i<6;i++)
		{
			getDebugDraw().DrawSegment(b2Vec2(0,i),b2Vec2(15,i),b2Color(1.0f,0.0f,0.0f));
		}

		for(int i=0;i<14;i++)
		{
			getDebugDraw().DrawSegment(b2Vec2(i,0),b2Vec2(i,5),b2Color(1.0f,0.0f,0.0f));
		}
		
		ParticleHolderManager::Render();
		//getGfx()->DrawLine(0,0,50,0);
		//getGfx()->DrawLine(5,0,50,0);
		//GetResManager()->getSprite(SPRITE_BOTTLE)->PaintFrame(0,0,0);
		if(m_GameplayNeedShowPath)
		{
			float t = 0.0f;
			float step = 0.01f;
			float tdir = 0;
			float sx,sy,ex,ey;
			sx = m_GameplayStartPointX;
			sy = m_GameplayStartPointY;
			
			float speed =0.5f;
			while(t<=1)
			{
				t+=step;
				ex = (1-t)*(1-t)*m_GameplayStartPointX + 2*(1-t)*t*m_GameplayControlPointX + t*t*m_GameplayEndPointX;
				ey = (1-t)*(1-t)*m_GameplayStartPointY + 2*(1-t)*t*m_GameplayControlPointY + t*t*m_GameplayEndPointY;

				float dir = sqrt((float)((ex-sx)*(ex-sx) + (ey-sy)*(ey-sy)));
				if(abs(tdir + dir - speed)<0.1f)	//1 dm
				{
					//getGfx()->DrawCircle2(ex,ey,5);
					getDebugDraw().DrawCircle(b2Vec2(ex,ey),0.04f,b2Color(1.0f,0.0f,0.0f));
					sx = ex;
					sy = ey;
					tdir = 0;
					step = 0.01;
				}
				else
				{
					if(tdir+dir < speed)
					{
						tdir += dir;
						sx = ex;
						sy = ey;
					}
					else
					{
						t-=step;
						step/=2;
					}
				}

						
			}

			
			/*float t = 0.0f;
			int sx,sy,ex,ey;
			sx = m_GameplayStartPointX;
			sy = m_GameplayStartPointY;
			
			getGfx()->SetColor(0xffff0000);
			while(t<=1)
			{
				ex = (1-t)*(1-t)*m_GameplayStartPointX + 2*(1-t)*t*m_GameplayControlPointX + t*t*m_GameplayEndPointX;
				ey = (1-t)*(1-t)*m_GameplayStartPointY + 2*(1-t)*t*m_GameplayControlPointY + t*t*m_GameplayEndPointY;

				getGfx()->DrawLine(sx,sy,ex,ey);
				if(t > 0.49f && t< 0.51f)
					getGfx()->DrawCircle2(ex,ey,5);

				sx = ex;
				sy = ey;

				t+=0.01;
			}*/
		}


	}
	else if(mode == (StateMachineMode::GainFocus))
	{		
		if(!m_isLoadDone)
		{
			//GetResManager()->setSpriteToLoad(SPRITE_BOTTLE);
			GetResManager()->setSpriteToLoad(SPRITE_FONT_SMALL);
			GetResManager()->setSpriteToLoad(SPRITE_END_GAME_BG);
			GetResManager()->setSpriteToLoad(SPRITE_ELECTRIC);
			GetResManager()->setSpriteToLoad(SPRITE_CHARACTER);
			PushState(State::GS_Loading);
		}
		else
		{
			CFpsParticleSystemSceneNode::InitPool( true);
			mp_Font = GL_NEW Font();
			mp_Font->LoadNormalSmallFont();

			m_GameplayStartPointX = 0.5f;
			m_GameplayStartPointY = 0.3f;

			m_objectManager = GL_NEW GameObjectManager();
			LoadWorld("data\\Level_1.xml");
			LoadEffectsPresets("data\\effects.xml");

			
			m_itemManager = GL_NEW ItemManager();
			m_itemManager->initialize();

			m_objectManager->GetGameObjects().AddObject(GL_NEW BaseBot());			

			m_robotFactory = GL_NEW RobotFactory();
			m_robotFactory->initialize();

			m_objectManager->GetGameObjects().AddObject(GL_NEW Room());

			m_cinematicManager = GL_NEW CinematicManager();
			m_cinematicManager->Init();
			

			m_cinematic = GL_NEW Cinematic("data/level_01_cinematic.cff");
			CinematicManager::Instance()->AddCinematic(m_cinematic);

			m_GameplayPrepareEnd = -1;


			m_objectManager->InitializeGameObjects();
			m_GameplayNeedShowPath = false;

			m_bTimeFrezze = false;
		}
	}
	else if(mode == (StateMachineMode::Destructor))
	{
	
	}

}

void CGame::LoadWorld(const char* levelFile)
{
	IXMLReader* levelXML = getFileSystem()->createXMLReader(levelFile);

	IAttributes* attributes = NULL;
	// read attributes
	while(levelXML->read())
	{
		bool endreached = false;

		EXML_NODE nType = levelXML->getNodeType();
		const WCHAR_T* name = levelXML->getNodeName();
		
		
		switch ( nType )
		{
		case EXN_ELEMENT_END:
			if (stringw(L"scene") == levelXML->getNodeName())
			{
				endreached = true;
			}
			break;
		case EXN_ELEMENT:
			if (stringw(L"attributes") == name)
			{
				attributes = getFileSystem()->createEmptyAttributes();
				attributes->read(levelXML, true);

				stringc gameType = attributes->getAttributeAsString("!GameType");


				if(gameType == "RobotCleaner")
				{
					GameObject* obj = m_objectManager->GetNewObject("RobotCleaner");
					//Robot* pRobot = GL_NEW Robot();
					obj->LoadParams(attributes);
					//m_objectManager->GetGameObjects().AddObject(pRobot);												
				}
						
					
				
			}
			break;
		default:
			break;
		}
	}

}

int	CGame::LoadEffectsPresets(const char* fileName)
{
	IXMLReader* xml = getFileSystem()->createXMLReader(fileName);

	if (!xml)
		return 1;

	while(xml->read())
	{
		if (stringw(L"effect") != xml->getNodeName())
		{
			continue;
		}

		IAttributes* attributes = NULL;

		CEffectPreset* pEffect = GL_NEW CEffectPreset(stringw(xml->getAttributeValue(WL("name"))));
		m_EffectsPresets.push_back(pEffect);

		while(xml->read())
		{
			bool endreached = false;

			switch (xml->getNodeType())
			{
			case EXN_ELEMENT_END:
				if (stringw(L"effect") == xml->getNodeName())
				{
					endreached = true;
				}
				break;

			case EXN_ELEMENT:
				if (stringw(L"ps")==xml->getNodeName())
				{
					while(xml->read())
					{
						bool ps_endreached = false;
						switch (xml->getNodeType())
						{
							case EXN_ELEMENT_END:
								if (stringw(L"ps") == xml->getNodeName())
								{
									ps_endreached = true;
								}
								break;

							case EXN_ELEMENT:
								if (stringw(L"attributes")==xml->getNodeName())
								{
									// read attributes
									attributes = getFileSystem()->createEmptyAttributes();
									attributes->read(xml, true);

									IFpsParticleSystemSceneNode* particleNode = GL_NEW CFpsParticleSystemSceneNode();

									particleNode->deserializeAttributes(attributes);

									m_EffectsPresets.getLast()->m_ParticleSystems.push_back(particleNode);

								}
								break;
						}

						if (ps_endreached)
							break;
					}
				}
				break;

			default:
				break;
			}

			if (endreached)
				break;
		}
	}

	xml->drop();
	return 0;
}